Categories
React

React App Routing with Wouter — Active Links, Trailing Slash, and Nested Paths

Spread the love

Wouter is a library that lets us loading React components according to URLs.

In this article, we’ll look at how to add routing to a React app with Wouter.

Active Links

We can set the active link by checking the isActive variable returned from the useRoute prop.

For instance, we can write:

import React from "react";
import { Link, Route, Router, useRoute } from "wouter";

const InboxPage = () => {
  return (
    <div>
      <p>inbox</p>
    </div>
  );
};

const UserPage = () => {
  const [, params] = useRoute("/users/:name");
  return <div>Hello, {params.name}!</div>;
};

const ActiveLink = (props) => {
  const [isActive] = useRoute(props.href);

  return (
    <Link {...props}>
      <a className={isActive ? "active" : ""}>{props.children}</a>
    </Link>
  );
};

export default function App() {
  return (
    <div>
      <style>
        {`.active {
            font-weight: bold
          }`}
      </style>
      <Router>
        <ActiveLink href="/users/foo">Users</ActiveLink>
        <ActiveLink href="/about">About</ActiveLink>
        <Route path="/about">
          <p>About Us</p>
        </Route>
        <Route path="/users/:name" component={UserPage}></Route>
        <Route path="/inbox" component={InboxPage} />
      </Router>
    </div>
  );
}

We have the ActiveLink component that calls the useRoute hook with the current URL and returns an array with the isActive variable.

isActive is true means the link for the current URL is active.

Trailing Slash

We can make Wouter match a route with the trailing slash with a custom URL matcher.

For instance, we can write:

import React from "react";
import { Route, Router } from "wouter";
import makeMatcher from "wouter/matcher";
import { pathToRegexp } from "path-to-regexp";

const customMatcher = makeMatcher((path) => {
  let keys = [];
  const regexp = pathToRegexp(path, keys, { strict: true });
  return { keys, regexp };
});

export default function App() {
  return (
    <div>
      <Router matcher={customMatcher}>
        <Route path="/foo">foo</Route>
        <Route path="/foo/">/foo/</Route>
      </Router>
    </div>
  );
}

We call makeMatcher with a callback to return an object with an object with strict set to true .

This will make sure that URLs with a trailing and without but otherwise are the same are considered different.

Nested Paths

We can add nested paths by setting the base path.

For instance, we can write:

import React from "react";
import { Link, Route, Router, useLocation, useRouter } from "wouter";

const NestedRoutes = (props) => {
  const router = useRouter();
  const [parentLocation] = useLocation();

  const nestedBase = `${router.base}${props.base}`;
  if (!parentLocation.startsWith(nestedBase)) return null;

  return (
    <Router base={nestedBase} key={nestedBase}>
      {props.children}
    </Router>
  );
};

export default function App() {
  return (
    <div>
      <Router>
        <Route path="/about">about</Route>
        <NestedRoutes base="/dashboard">
          <Link to="/users" />
          <Route path="/users">users</Route>
        </NestedRoutes>
      </Router>
    </div>
  );
}

We created the NestedRoutes component that takes the base prop to set the base path.

From it, we created the nestedBase variable by combining router.base and props.base to create the base path.

Then we set the base prop’s value to nestedBase to set the nested routes’ base path.

Conclusion

We can check which link is active, adding trailing slash matches, and nested paths with Wouter.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *